"""
机器学习专用插件
"""
from typing import Any

# 修改导入语句，使用绝对导入而不是相对导入
from plugins.base_plugin import BasePlugin
import numpy as np
import time
import random
import json
from core.logger import get_logger

# 获取日志记录器
logger = get_logger(__name__)



class DataContinuity(BasePlugin):

    # 数据完整性检查插件
    def execute(self, input_data: Any) -> dict:
        """执行特征工程"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data

        config = self.config.get("config", {})
        column_name = config.get("column_name", "")
        interval = config.get("interval", 60)
        # 检查行是否连续，记录缺失点和缺失率
        last_timestamp = None
        missing_points = []
        for record in raw_data:
            if column_name not in record:
                logger.error(f"Record missing timestamp column: {record}")
                continue

            timestamp = record[column_name]
            if last_timestamp is not None and timestamp - last_timestamp != interval:
                logger.warning(f"Timestamp gap detected: {timestamp} - {last_timestamp}")
                missing_points.append(timestamp)

            last_timestamp = timestamp

        missing_rate = len(missing_points) / len(raw_data)
        logger.info(f"Data missing rate: {missing_rate:.2f}")
        return {
            "missing_rate": missing_rate,
            "missing_points": missing_points,
            "continuity_check_by": self.plugin_id
        }

class DataEmptyValue(BasePlugin):

    # 数据完整性检查插件
    def execute(self, input_data: Any) -> dict:
        """执行特征工程"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data

        # 检查数据集是否存在空值，记录缺失点所在的行和缺失率
        empty_points = []
        for record in raw_data:
            for value in record.values():
                # 合并空值检查逻辑：字符串空值、None值、NaN值
                if (isinstance(value, str) and value.strip() == "") or \
                        value is None or \
                        (isinstance(value, float) and np.isnan(value)):
                    empty_points.append(record)
                    break
        empty_rate = len(empty_points) / len(raw_data)
        logger.info(f"Data empty rate: {empty_rate:.2f}")
        return {
            "empty_rate": empty_rate,
            "empty_points": empty_points,
            "empty_check_by": self.plugin_id
        }

class DataOutOfRange(BasePlugin):

    # 数据完整性检查插件
    def execute(self, input_data: Any) -> dict:
        """执行特征工程"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data


        config = self.config.get("config", {})
        column_names = config.get("column_names", [])
        threshold_range = config.get("threshold_range", [])

        # 检查数据集是否存在超出阈值的值，记录超出点所在的行和超出率
        out_of_range_points = []
        for record in raw_data:
            for key, value in record.items():
                if key not in column_names:
                    continue
                index = column_names.index(key)
                threshold_lower, threshold_upper = threshold_range[index]
                if not (threshold_lower <= value <= threshold_upper):
                    out_of_range_points.append(record)
                    break

        out_of_range_rate = len(out_of_range_points) / len(raw_data)
        logger.info(f"Data out of range rate: {out_of_range_rate:.2f}")
        return {
            "out_of_range_rate": out_of_range_rate,
            "out_of_range_points": out_of_range_points,
            "out_of_range_check_by": self.plugin_id
        }

class DataMeanStatistics(BasePlugin):
    # 数据均值统计插件
    def execute(self, input_data: Any) -> dict:
        """执行特征工程"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data

        config = self.config.get("config", {})
        column_names = config.get("column_names", [])

        # 计算数据集每列的均值
        mean_statistics = {}
        for column_name in column_names:
            column_values = [record[column_name] for record in raw_data if column_name in record]
            if column_values:
                mean_statistics[column_name] = np.mean(column_values)
            else:
                mean_statistics[column_name] = None

        logger.info(f"Data mean statistics: {mean_statistics}")
        return {
            "mean_statistics": mean_statistics,
            "mean_statistics_check_by": self.plugin_id
        }


class DataMedianStatistics(BasePlugin):
    # 中位数统计插件
    def execute(self, input_data: Any) -> dict:
        """计算中位数"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data

        config = self.config.get("config", {})
        column_names = config.get("column_names", [])

        # 计算数据集每列的中位数
        median_statistics = {}
        for column_name in column_names:
            column_values = [record[column_name] for record in raw_data if column_name in record]
            if column_values:
                median_statistics[column_name] = np.median(column_values)
            else:
                median_statistics[column_name] = None

        logger.info(f"Data median statistics: {median_statistics}")
        return {
            "median_statistics": median_statistics,
            "median_statistics_check_by": self.plugin_id
        }


class DataStdStatistics(BasePlugin):
    # 标准差统计插件
    def execute(self, input_data: Any) -> dict:
        """计算标准差"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data

        config = self.config.get("config", {})
        column_names = config.get("column_names", [])

        # 计算数据集每列的标准差
        std_statistics = {}
        for column_name in column_names:
            column_values = [record[column_name] for record in raw_data if column_name in record]
            if len(column_values) > 1:
                std_statistics[column_name] = np.std(column_values, ddof=1)  # 样本标准差
            elif len(column_values) == 1:
                std_statistics[column_name] = 0.0  # 只有一个样本时标准差为0
            else:
                std_statistics[column_name] = None

        logger.info(f"Data standard deviation statistics: {std_statistics}")
        return {
            "std_statistics": std_statistics,
            "std_statistics_check_by": self.plugin_id
        }


class DataSkewnessStatistics(BasePlugin):
    # 偏度统计插件
    def execute(self, input_data: Any) -> dict:
        """计算偏度"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data

        config = self.config.get("config", {})
        column_names = config.get("column_names", [])

        # 计算数据集每列的偏度
        skewness_statistics = {}
        for column_name in column_names:
            column_values = [record[column_name] for record in raw_data if column_name in record]
            if len(column_values) >= 3:  # 至少需要3个样本计算偏度
                skewness_statistics[column_name] = self._calculate_skewness(column_values)
            else:
                skewness_statistics[column_name] = None

        logger.info(f"Data skewness statistics: {skewness_statistics}")
        return {
            "skewness_statistics": skewness_statistics,
            "skewness_statistics_check_by": self.plugin_id
        }
    
    def _calculate_skewness(self, data):
        """计算偏度（三阶矩）"""
        data = np.array(data)
        mean = np.mean(data)
        std_dev = np.std(data, ddof=1)
        
        if std_dev == 0:
            return 0.0
        
        # 计算三阶中心矩
        third_moment = np.mean((data - mean) ** 3)
        skewness = third_moment / (std_dev ** 3)
        return float(skewness)


class DataKurtosisStatistics(BasePlugin):
    # 峰度统计插件
    def execute(self, input_data: Any) -> dict:
        """计算峰度"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data

        config = self.config.get("config", {})
        column_names = config.get("column_names", [])

        # 计算数据集每列的峰度
        kurtosis_statistics = {}
        for column_name in column_names:
            column_values = [record[column_name] for record in raw_data if column_name in record]
            if len(column_values) >= 4:  # 至少需要4个样本计算峰度
                kurtosis_statistics[column_name] = self._calculate_kurtosis(column_values)
            else:
                kurtosis_statistics[column_name] = None

        logger.info(f"Data kurtosis statistics: {kurtosis_statistics}")
        return {
            "kurtosis_statistics": kurtosis_statistics,
            "kurtosis_statistics_check_by": self.plugin_id
        }
    
    def _calculate_kurtosis(self, data):
        """计算峰度（四阶矩）"""
        data = np.array(data)
        mean = np.mean(data)
        std_dev = np.std(data, ddof=1)
        
        if std_dev == 0:
            return -3.0  # 超额峰度为-3
        
        # 计算四阶中心矩
        fourth_moment = np.mean((data - mean) ** 4)
        kurtosis = fourth_moment / (std_dev ** 4)
        
        # 返回超额峰度（减去3，使得正态分布的峰度为0）
        excess_kurtosis = kurtosis - 3
        return float(excess_kurtosis)


class DataCategoryStatistics(BasePlugin):
    """类别统计插件 - 统计每个类别的数量"""
    
    def execute(self, input_data: Any) -> dict:
        """执行类别统计"""
        if isinstance(input_data, dict) and "raw_data" in input_data:
            raw_data = input_data["raw_data"]
        else:
            raw_data = input_data

        config = self.config.get("config", {})
        column_names = config.get("column_names", [])

        # 统计每个类别列的类别分布
        category_statistics = {}
        for column_name in column_names:
            # 收集该列的所有值
            column_values = []
            for record in raw_data:
                if column_name in record and record[column_name] is not None:
                    column_values.append(record[column_name])
            
            # 统计每个类别的数量
            if column_values:
                unique_values, counts = np.unique(column_values, return_counts=True)
                category_counts = {}
                for value, count in zip(unique_values, counts):
                    # 处理numpy数据类型
                    if hasattr(value, 'item'):
                        value = value.item()
                    category_counts[str(value)] = int(count)
                
                category_statistics[column_name] = {
                    "total_categories": len(unique_values),
                    "category_counts": category_counts,
                    "most_frequent": str(unique_values[np.argmax(counts)]),
                    "most_frequent_count": int(np.max(counts))
                }
            else:
                category_statistics[column_name] = {
                    "total_categories": 0,
                    "category_counts": {},
                    "most_frequent": None,
                    "most_frequent_count": 0
                }

        logger.info(f"Data category statistics: {category_statistics}")
        return {
            "category_statistics": category_statistics,
            "category_statistics_check_by": self.plugin_id
        }